# -*- coding: utf-8 -*-
"""
配置管理模块
统一管理应用的各种配置参数
"""

import json
import os
from typing import Dict, Any, Optional
from dataclasses import dataclass, asdict


@dataclass
class ChunkingConfig:
    """分块配置类"""
    # 默认分块参数
    default_separator: str = "#"
    default_min_length: int = 100
    default_max_length: int = 1000
    default_overlap: int = 100
    default_timeout: int = 30
    
    # 支持的文件格式
    supported_formats: tuple = ('.docx', '.txt', '.pdf')
    
    # 输出格式
    output_formats: tuple = ('txt', 'json', 'markdown')
    
    # 默认输出格式
    default_output_format: str = 'txt'


@dataclass
class UIConfig:
    """UI配置类"""
    # 窗口配置
    window_width: int = 800
    window_height: int = 600
    window_resizable: bool = True
    
    # 字体配置
    font_family: str = '微软雅黑'
    font_size: int = 10
    
    # 主题配置
    theme: str = 'default'
    
    # 日志配置
    log_max_lines: int = 1000
    log_auto_scroll: bool = True


@dataclass
class ProcessingConfig:
    """处理配置类"""
    # 并发配置
    max_workers: int = 4
    batch_size: int = 10
    
    # 内存配置
    max_memory_usage: int = 512  # MB
    
    # 缓存配置
    enable_cache: bool = True
    cache_dir: str = "cache"
    cache_max_size: int = 100  # MB
    
    # 错误处理
    max_retries: int = 3
    retry_delay: float = 1.0  # seconds


@dataclass
class LoggingConfig:
    """日志配置类"""
    # 日志级别
    level: str = "INFO"
    
    # 日志格式
    format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    
    # 日志文件
    log_file: str = "logs/chunker.log"
    
    # 日志文件大小限制
    max_file_size: int = 10  # MB
    
    # 保留的日志文件数量
    backup_count: int = 5
    
    # 控制台输出
    console_output: bool = True


class ConfigManager:
    """配置管理器"""
    
    def __init__(self, config_file: str = "config/app_config.json"):
        """初始化配置管理器
        
        Args:
            config_file: 配置文件路径
        """
        self.config_file = config_file
        self.chunking = ChunkingConfig()
        self.ui = UIConfig()
        self.processing = ProcessingConfig()
        self.logging = LoggingConfig()
        
        # 加载配置
        self.load_config()
        
    def load_config(self) -> bool:
        """从文件加载配置
        
        Returns:
            是否成功加载配置
        """
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    config_data = json.load(f)
                    
                # 更新配置对象
                if 'chunking' in config_data:
                    self._update_dataclass(self.chunking, config_data['chunking'])
                if 'ui' in config_data:
                    self._update_dataclass(self.ui, config_data['ui'])
                if 'processing' in config_data:
                    self._update_dataclass(self.processing, config_data['processing'])
                if 'logging' in config_data:
                    self._update_dataclass(self.logging, config_data['logging'])
                    
                return True
            else:
                # 如果配置文件不存在，创建默认配置
                self.save_config()
                return True
                
        except Exception as e:
            print(f"加载配置文件失败: {e}")
            return False
            
    def save_config(self) -> bool:
        """保存配置到文件
        
        Returns:
            是否成功保存配置
        """
        try:
            # 确保配置目录存在
            os.makedirs(os.path.dirname(self.config_file), exist_ok=True)
            
            config_data = {
                'chunking': asdict(self.chunking),
                'ui': asdict(self.ui),
                'processing': asdict(self.processing),
                'logging': asdict(self.logging)
            }
            
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(config_data, f, indent=2, ensure_ascii=False)
                
            return True
            
        except Exception as e:
            print(f"保存配置文件失败: {e}")
            return False
            
    def _update_dataclass(self, obj: Any, data: Dict[str, Any]):
        """更新数据类对象的属性
        
        Args:
            obj: 数据类对象
            data: 更新数据
        """
        for key, value in data.items():
            if hasattr(obj, key):
                setattr(obj, key, value)
                
    def get_chunking_config(self) -> ChunkingConfig:
        """获取分块配置
        
        Returns:
            分块配置对象
        """
        return self.chunking
        
    def get_ui_config(self) -> UIConfig:
        """获取UI配置
        
        Returns:
            UI配置对象
        """
        return self.ui
        
    def get_processing_config(self) -> ProcessingConfig:
        """获取处理配置
        
        Returns:
            处理配置对象
        """
        return self.processing
        
    def get_logging_config(self) -> LoggingConfig:
        """获取日志配置
        
        Returns:
            日志配置对象
        """
        return self.logging
        
    def update_chunking_config(self, **kwargs):
        """更新分块配置
        
        Args:
            **kwargs: 配置参数
        """
        for key, value in kwargs.items():
            if hasattr(self.chunking, key):
                setattr(self.chunking, key, value)
                
    def update_ui_config(self, **kwargs):
        """更新UI配置
        
        Args:
            **kwargs: 配置参数
        """
        for key, value in kwargs.items():
            if hasattr(self.ui, key):
                setattr(self.ui, key, value)
                
    def update_processing_config(self, **kwargs):
        """更新处理配置
        
        Args:
            **kwargs: 配置参数
        """
        for key, value in kwargs.items():
            if hasattr(self.processing, key):
                setattr(self.processing, key, value)
                
    def update_logging_config(self, **kwargs):
        """更新日志配置
        
        Args:
            **kwargs: 配置参数
        """
        for key, value in kwargs.items():
            if hasattr(self.logging, key):
                setattr(self.logging, key, value)
                
    def reset_to_defaults(self):
        """重置为默认配置"""
        self.chunking = ChunkingConfig()
        self.ui = UIConfig()
        self.processing = ProcessingConfig()
        self.logging = LoggingConfig()
        
    def export_config(self, export_file: str) -> bool:
        """导出配置到指定文件
        
        Args:
            export_file: 导出文件路径
            
        Returns:
            是否成功导出
        """
        try:
            config_data = {
                'chunking': asdict(self.chunking),
                'ui': asdict(self.ui),
                'processing': asdict(self.processing),
                'logging': asdict(self.logging)
            }
            
            with open(export_file, 'w', encoding='utf-8') as f:
                json.dump(config_data, f, indent=2, ensure_ascii=False)
                
            return True
            
        except Exception as e:
            print(f"导出配置失败: {e}")
            return False
            
    def import_config(self, import_file: str) -> bool:
        """从指定文件导入配置
        
        Args:
            import_file: 导入文件路径
            
        Returns:
            是否成功导入
        """
        try:
            if not os.path.exists(import_file):
                print(f"配置文件不存在: {import_file}")
                return False
                
            with open(import_file, 'r', encoding='utf-8') as f:
                config_data = json.load(f)
                
            # 更新配置对象
            if 'chunking' in config_data:
                self._update_dataclass(self.chunking, config_data['chunking'])
            if 'ui' in config_data:
                self._update_dataclass(self.ui, config_data['ui'])
            if 'processing' in config_data:
                self._update_dataclass(self.processing, config_data['processing'])
            if 'logging' in config_data:
                self._update_dataclass(self.logging, config_data['logging'])
                
            return True
            
        except Exception as e:
            print(f"导入配置失败: {e}")
            return False


# 全局配置管理器实例
config_manager = ConfigManager()